package com.site.blog.my.core.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.site.blog.my.core.config.CommonLocalSetting;
import com.site.blog.my.core.entity.FileInfo;
import com.site.blog.my.core.enums.FileSaveType;
import com.site.blog.my.core.enums.SystemConfigName;
import com.site.blog.my.core.enums.ThemeType;
import com.site.blog.my.core.exception.AppException;
import com.site.blog.my.core.service.FileInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author xuwangcheng
 * @version 1.0.0
 * @description
 * @date 2020/3/25 14:31
 */
public class FileUtil extends cn.hutool.core.io.FileUtil {
    private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);

    /**
     *  删除保存的文件
     * @author xuwangcheng
     * @date 2020/12/17 10:15
     * @param fileInfo fileInfo
     * @return {@link boolean}
     */
    public static boolean deleteSaveFile (FileInfo fileInfo) {
        if (fileInfo == null) {
            return false;
        }
        if (FileSaveType.QI_NIU.getType().equals(fileInfo.getSaveType())) {
            deleteFileFromQiNiu(fileInfo);
        } else {
            try {
                FileUtil.del(fileInfo.getDiskPath());
            } catch (IORuntimeException e) {
                throw new AppException("删除本地文件出错!");
            }
        }

        return true;
    }

    /**
     *  保存上传的文件
     * @author xuwangcheng
     * @date 2020/12/17 10:15
     * @param file file
     * @return {@link FileInfo}
     */
    public static FileInfo saveUploadFile (MultipartFile file, boolean saveDb) throws IOException {
        FileInfo fileInfo = new FileInfo();
        fileInfo.setFileName(file.getOriginalFilename());
        int split = fileInfo.getFileName().lastIndexOf(".");
        String extName = "";
        if (split > 0) {
            extName = fileInfo.getFileName().substring(split + 1);
        }
        fileInfo.setFileType(extName);
        fileInfo.setSaveType(CommonLocalSetting.getCustomSetting().getConfigValue(SystemConfigName.fileSaveType));
        // 判断是本地保存还是七牛云保存
        if (FileSaveType.QI_NIU.getType().equals(fileInfo.getSaveType())) {
            uploadFileToQiNiu(file.getBytes(), fileInfo);
        } else {
            // 默认本地保存
            saveLocalFile(fileInfo, file);
        }

        fileInfo.setCreateTime(new Date());

        if (saveDb) {
            FileInfoService fileInfoService = SpringContextUtils.getBean(FileInfoService.class);
            fileInfoService.saveFile(fileInfo);
        }
        
        return fileInfo;

    }

    /**
     *  保存文件到本地
     * @author xuwangcheng
     * @date 2020/12/16 9:58
     * @param fileInfo fileInfo
     * @param uploadFile uploadFile
     * @return
     */
    private static void saveLocalFile (FileInfo fileInfo, MultipartFile uploadFile) {
        try {
            FileUtil.createFilePath(fileInfo);
            //写入文件到本地
            File file1 = new File(fileInfo.getDiskPath());
            uploadFile.transferTo(file1);
            fileInfo.setSize(FileUtil.size(file1));
        } catch (IOException e) {
            throw new AppException("文件本地保存失败,请检查配置");
        }


    }

    /**
     * 设定文件的磁盘路径和网络路径
     * @author xuwangcheng
     * @date 2019/7/24 8:56
     * @param fileInfo fileInfo
     */
    public static void createFilePath(FileInfo fileInfo) {
        if (StrUtil.isNotBlank(fileInfo.getFileName())) {
            String fileName = fileInfo.getFileName();
            String dailyFolderPath = getDailyFolderPath();


            //判断文件夹是否存在
            String diskDirPath = CommonLocalSetting.getCustomSetting().getConfigValue(SystemConfigName.localFilePath) + File.separator + dailyFolderPath;
            File file2 = new File(diskDirPath);
            if(!file2.exists() && !file2.isDirectory()){
                file2.mkdirs();
            }

            //磁盘路径
            String diskPath = diskDirPath + fileName;

            //防止重名文件覆盖
            if (FileUtil.exist(diskPath)) {
                fileName = fileName.substring(0, fileName.lastIndexOf(".")) + "_" + System.currentTimeMillis()
                        + (StrUtil.isBlank(fileInfo.getFileType()) ? "" : ("." + fileInfo.getFileType()));
            }

            fileInfo.setPath(dailyFolderPath + fileName);
            fileInfo.setDiskPath(diskPath);
        }
    }


    /**
     * 获取按日按月按年分类的文件存储目录： 2019/06/03/
     * @author xuwangcheng
     * @date 2019/6/3 12:22
     * @param
     * @return {@link String}
     */
    private static String getDailyFolderPath() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());

        String dailyFolderPath = calendar.get(Calendar.YEAR) + File.separator + (calendar.get(Calendar.MONTH) + 1)
                + File.separator + calendar.get(Calendar.DAY_OF_MONTH) + File.separator;

        return dailyFolderPath;
    }

    /**
     *  获取主题列表
     * @author xuwangcheng
     * @date 2020/3/25 21:58
     * @param
     * @return {@link List}
     */
    public static List<String> getThemeNames () {
        List<String> themeNames = CollUtil.newArrayList();
        for (ThemeType themeType:ThemeType.values()) {
            themeNames.add(themeType.getThemeName());
        }
        return themeNames;
    }

    /**
     *  上传文件到七牛云
     * @author xuwangcheng
     * @date 2020/12/17 10:15
     * @param bs bs
     * @param fileInfo fileInfo
     * @return
     */
    private static void uploadFileToQiNiu(byte[] bs, FileInfo fileInfo) {
        fileInfo.setSize((long) bs.length);
        Configuration cfg = new Configuration(Zone.zone0());
        UploadManager uploadManager = new UploadManager(cfg);
        fileInfo.setPath(UUID.fastUUID().toString().replaceAll("\\-", "") + "." + fileInfo.getFileType());
        Auth auth = Auth.create(CommonLocalSetting.getCustomSetting().getConfigValue(SystemConfigName.qiniuAccessKey)
                , CommonLocalSetting.getCustomSetting().getConfigValue(SystemConfigName.qiniuSecretKey));
        String upToken = auth.uploadToken(CommonLocalSetting.getCustomSetting().getConfigValue(SystemConfigName.qiniuBucket));
        try {
            Response response = uploadManager.put(bs, fileInfo.getPath(), upToken);
            logger.info("七牛云上传成功：" + response.bodyString());
        } catch (QiniuException ex) {
            throw new AppException("七牛云上传失败，请检查配置信息：" + ex.error());
        }
    }

    /**
     *  从七牛云删除文件
     * @author xuwangcheng
     * @date 2020/12/17 10:14
     * @param fileInfo fileInfo
     * @return
     */
    private static void deleteFileFromQiNiu (FileInfo fileInfo) {
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone0());
        Auth auth = Auth.create(CommonLocalSetting.getCustomSetting().getConfigValue(SystemConfigName.qiniuAccessKey)
                , CommonLocalSetting.getCustomSetting().getConfigValue(SystemConfigName.qiniuSecretKey));
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            bucketManager.delete(CommonLocalSetting.getCustomSetting().getConfigValue(SystemConfigName.qiniuBucket), fileInfo.getPath());
        } catch (QiniuException ex) {
            throw new AppException("七牛云删除文件失败，请检查配置信息");
        }
    }
}
